home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Pascal / Applications / ircle 1.5.1 / source / ircle sources / IRCChannels.p < prev    next >
Encoding:
Text File  |  1993-10-30  |  8.6 KB  |  428 lines  |  [TEXT/PJMM]

  1. {    ircle - Internet Relay Chat client    }
  2. {    File: IRCChannels    }
  3. {    Copyright © 1992 Olaf Titz (s_titz@ira.uka.de)    }
  4.  
  5. {    This program is free software; you can redistribute it and/or modify    }
  6. {    it under the terms of the GNU General Public License as published by    }
  7. {    the Free Software Foundation; either version 2 of the License, or    }
  8. {    (at your option) any later version.    }
  9.  
  10. {    This program is distributed in the hope that it will be useful,    }
  11. {    but WITHOUT ANY WARRANTY; without even the implied warranty of    }
  12. {    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    }
  13. {    GNU General Public License for more details.    }
  14.  
  15. {    You should have received a copy of the GNU General Public License    }
  16. {    along with this program; if not, write to the Free Software    }
  17. {    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.    }
  18.  
  19. unit IRCChannels;
  20. { Deals with the window-per-channel interface and all messages to the user. }
  21.  
  22. interface
  23.  
  24. uses
  25.     TCPTypes, TCPStuff, TCPConnections, ApplBase, MiscGlue, MsgWindows, IRCGlobals, IRCaux;
  26.  
  27. var
  28.     windowarg: Rect; { holds size of next window to open }
  29.  
  30. procedure InitIRCChannels;
  31. { Startup }
  32.  
  33. procedure LineMsg (var s: string);
  34. { Display message in main window }
  35.  
  36. procedure StatusMsg (n: integer);
  37. { Display message from STR# 256 }
  38.  
  39. procedure SetMainTitle (var newtitle: string);
  40. { Call this after changing nick }
  41.  
  42. function DoJoin (var ch: string): MWHndl;
  43. { Open channel window for ch -- this may as well be a queried nick }
  44.  
  45. procedure DoPart (var ch: string);
  46. { Close channel window for ch }
  47.  
  48. procedure partWindow (p: WindowPtr);
  49. { user closing window}
  50.  
  51. procedure ChannelMsg (var ch, msg: string);
  52. { Display msg in the window for channel ch, }
  53. { or in the frontmost window if a ch window does not exist }
  54.  
  55. procedure Message (var msg: string);
  56. { Display msg in current window }
  57.  
  58. procedure Inactive (var ch: string);
  59. { mark a window as inactive }
  60.  
  61. procedure GetAllWindows (channels, queries, chats: boolean; sepa: char; var s: string);
  62. { make list of all active target windows }
  63.  
  64. function ChannelWindow (var ch: string): MWHndl;
  65. { find the window with given title }
  66.  
  67. implementation
  68.  
  69. type
  70.     CPtr = ^Clist;
  71.     Clist = record
  72.             n: CPtr;
  73.             w: MWHndl;
  74.             mp: integer;
  75.         end;
  76.  
  77. var
  78.     mwin: MWHndl;
  79.     CW: Cptr;
  80.     noti: NMRec;
  81.     SIcon, Sound: Handle;
  82.  
  83. procedure remove (q: NMPtr);
  84.     var
  85.         ca5: longint;
  86.     begin
  87.         ca5 := setA5(q^.nmRefCon);
  88.         if notified then
  89.             notified := (NMRemove(@noti) <> 0);
  90.         ca5 := setA5(ca5);
  91.     end;
  92.  
  93. procedure NotifyUser (blink, beep, bkgnd: boolean);
  94.     begin
  95.         if blink or beep then begin
  96.             if blink then
  97.                 noti.nmSIcon := SIcon
  98.             else
  99.                 noti.nmSIcon := nil;
  100.             if beep then
  101.                 noti.nmSound := Sound
  102.             else
  103.                 noti.nmSound := nil;
  104.             if bkgnd then
  105.                 noti.nmResp := nil
  106.             else
  107.                 noti.nmResp := @remove;
  108.             if not notified then
  109.                 notified := (NMInstall(@noti) = 0);
  110.         end;
  111.     end;
  112.  
  113. procedure hideit (w: WindowPtr);
  114.     begin
  115.         HideWindow(w)
  116.     end;
  117.  
  118. function DoMSGWindow: boolean;
  119.     var
  120.         r: rect;
  121.     begin
  122.         if mwin = nil then begin
  123.             SetRect(r, 0, 0, 0, 0);
  124.             mwin := NewMWindow(CurrentNick, r, @hideit);
  125.             lastWindow := mwin;
  126.             DoMsgWindow := false
  127.         end
  128.         else begin
  129.             DoMsgWindow := (mwin^^.w <> FrontWindow);
  130.         end;
  131.         ShowWindow(mwin^^.w);
  132.     end;
  133.  
  134. procedure CommonMsg (var m: string; noti: boolean);
  135.     begin
  136.         if logging then
  137.             writeln(logfile, m);
  138.         if noti then
  139.             if inBackground then
  140.                 NotifyUser(default^^.notify[3], default^^.notify[4], true)
  141.             else
  142.                 NotifyUser(default^^.notify[1], default^^.notify[2], false);
  143.     end;
  144.  
  145. procedure LineMsg (var s: string);
  146.     var
  147.         b: boolean;
  148.     begin
  149.         b := DOMSGWindow;
  150.         MWMessage(mwin, s);
  151.         b := (lastWindow <> mwin);
  152.         lastWindow := mwin;
  153.         CommonMsg(s, b);
  154.     end;
  155.  
  156. procedure StatusMsg (n: integer);
  157.     var
  158.         s: str255;
  159.         b: boolean;
  160.     begin
  161.         b := DOMsgWindow;
  162.         GetIndString(s, 256, n);
  163.         MWMessage(mwin, s);
  164.     end;
  165.  
  166. procedure SetMainTitle (var newtitle: string);
  167.     begin
  168.         if mwin <> nil then
  169.             SetWTitle(mwin^^.w, newtitle);
  170.         SetItem(GetMHandle(M_WINDOWS), M_WI_MAIN, newtitle);
  171.         EnableItem(GetMHandle(M_WINDOWS), M_WI_MAIN);
  172.     end;
  173.  
  174. procedure NormTitle (var s: string);
  175.     begin
  176.         if s[1] = INACTIVE_PREFIX then begin
  177.             delete(s, 1, 1);
  178.             s[0] := pred(s[0]);
  179.         end
  180.     end;
  181.  
  182.  
  183. function ChannelWindow (var ch: string): MWHndl;
  184.     var
  185.         s: Str255;
  186.         l: CPtr;
  187.     begin
  188.         l := CW;
  189.         NormTitle(ch);
  190.         while l <> nil do begin
  191.             GetWTitle(l^.w^^.w, s);
  192.             NormTitle(s);
  193.             if EqualString(ch, s, false, true) then begin
  194.                 ChannelWindow := l^.w;
  195.                 exit(ChannelWindow)
  196.             end;
  197.             l := l^.n
  198.         end;
  199.         ChannelWindow := nil
  200.     end;
  201.  
  202.  
  203. function activate (var e: EventRecord): boolean;
  204.     var
  205.         p: CPtr;
  206.         s: string;
  207.     begin
  208.         activate := false;
  209.         if odd(e.modifiers) then begin
  210.             p := CW;
  211.             while p <> nil do begin
  212.                 if p^.w^^.w = WindowPtr(e.message) then begin
  213.                     GetWTitle(p^.w^^.w, CurrentTarget);
  214.                     if CurrentTarget[1] = INACTIVE_PREFIX then
  215.                         CurrentTarget := '';
  216.                     UpdateStatusLine;
  217.                     exit(activate)
  218.                 end;
  219.                 p := p^.n
  220.             end;
  221.             currentTarget := '';
  222.             UpdateStatusLine;
  223.         end
  224.     end;
  225.  
  226. function Switcher (var e: EventRecord): boolean;
  227.     var
  228.         i: integer;
  229.     begin
  230.         inBackground := (bitand(e.message, 1) = 0);
  231.         if not InBackground then
  232.             InitCursor;
  233.         if notified then
  234.             i := NMRemove(@noti);
  235.         notified := false;
  236.         Switcher := false
  237.     end;
  238.  
  239. function wmenu (var e: EventRecord): boolean;
  240.     var
  241.         l: CPtr;
  242.         s: str255;
  243.     begin
  244.         case e.message of
  245.             M_WI_CYCLE: 
  246.                 begin
  247.                 SendBehind(FrontWindow, nil);
  248.                 GetWTitle(FrontWindow, s);
  249.                 if s = '' then
  250.                     SendBehind(FrontWindow, nil);
  251.             end;
  252.             M_WI_MAIN: 
  253.                 if mwin <> nil then begin
  254.                     ShowWindow(mwin^^.w);
  255.                     SelectWindow(mwin^^.w);
  256.                 end;
  257.             otherwise
  258.                 begin
  259.                 l := CW;
  260.                 while l <> nil do begin
  261.                     if l^.mp = e.message then begin
  262.                         SelectWindow(l^.w^^.w);
  263.                         leave
  264.                     end;
  265.                     l := l^.n;
  266.                 end;
  267.                 wmenu := true
  268.             end
  269.         end
  270.     end;
  271.  
  272. procedure partWindow (p: WindowPtr); {user closing window}
  273.     var
  274.         p0, p1: CPtr;
  275.         s: str255;
  276.     begin
  277.         GetWTitle(p, s);
  278.         if IsChannel(s) then begin
  279.             s := concat('PART ', s);
  280.             PutLine(s);
  281.         end
  282.         else { inactive/query window }
  283.             begin
  284.             NormTitle(s);
  285.             DoPart(s);
  286.         end;
  287.     end;
  288.  
  289. function DoJoin (var ch: string): MWHndl; {callback from server}
  290.     var
  291.         w: MWHndl;
  292.         l: CPtr;
  293.         r: rect;
  294.         i: integer;
  295.     begin
  296.         w := ChannelWindow(ch);
  297.         if w = nil then begin
  298.             w := NewMWindow(ch, windowarg, @partWindow);
  299.             InsMenuItem(GetMHandle(M_WINDOWS), ch, 255);
  300.             new(l);
  301.             l^.n := CW;
  302.             CW := l;
  303.             l^.w := w;
  304.             l^.mp := CountMItems(GetMHandle(M_WINDOWS));
  305.             SetRect(windowarg, 0, 0, 0, 0);
  306.         end
  307.         else begin
  308.             SelectWindow(w^^.w);
  309.             SetWTitle(w^^.w, ch);
  310.         end;
  311.         DoJoin := w
  312.     end;
  313.  
  314. procedure DoPart (var ch: string); {callback from server}
  315.     var
  316.         l, l0: CPtr;
  317.         n: integer;
  318.         s: Str255;
  319.     begin
  320.         l := CW;
  321.         while l <> nil do begin
  322.             GetWTitle(l^.w^^.w, s);
  323.             NormTitle(s);
  324.             if EqualString(ch, s, false, true) then begin
  325.                 n := l^.mp;
  326.                 DelMenuItem(GetMHandle(M_WINDOWS), n);
  327.                 DeleteMWindow(l^.w);
  328.                 if l = CW then
  329.                     CW := l^.n
  330.                 else
  331.                     l0^.n := l^.n;
  332.                 leave;
  333.             end;
  334.             l0 := l;
  335.             l := l0^.n
  336.         end;
  337.         l := CW;
  338.         while l <> nil do begin
  339.             if l^.mp > n then
  340.                 l^.mp := pred(l^.mp);
  341.             l := l^.n
  342.         end;
  343.     end;
  344.  
  345. procedure ChannelMsg (var ch, msg: string);
  346.     var
  347.         m: MWHndl;
  348.         b: boolean;
  349.     begin
  350.         m := ChannelWindow(ch);
  351.         if m = nil then begin
  352.             m := ChannelWindow(CurrentTarget);
  353.             if m = nil then begin
  354.                 b := DOMSGWindow;
  355.                 m := mwin
  356.             end;
  357.         end;
  358.         lastWindow := m;
  359.         MWMessage(m, msg);
  360.         CommonMsg(msg, m^^.w <> FrontWindow);
  361.     end;
  362.  
  363. procedure Message (var msg: string);
  364.     begin
  365.         ChannelMsg(CurrentTarget, msg)
  366.     end;
  367.  
  368.  
  369. procedure InitIRCChannels;
  370.     var
  371.         i: integer;
  372.     begin
  373.         mwin := nil;
  374.         CW := nil;
  375.         i := ApplTask(@activate, activateEvt);
  376.         i := ApplTask(@Switcher, app4Evt);
  377.         i := ApplTask(@wmenu, menuMsg + M_WINDOWS);
  378.         SIcon := GetResource('SICN', 128);
  379.         Sound := GetResource('snd ', 128);
  380.         with noti do begin
  381.             qType := 8;
  382.             nmMark := 1;
  383.             nmStr := nil;
  384.             nmRefCon := SetCurrentA5;
  385.         end;
  386.         SetRect(windowarg, 0, 0, 0, 0);
  387.     end;
  388.  
  389. procedure Inactive (var ch: string);
  390.     var
  391.         m: MWHndl;
  392.         s: string;
  393.     begin
  394.         m := ChannelWindow(ch);
  395.         if m <> nil then begin
  396.             s := concat(INACTIVE_PREFIX, ch, INACTIVE_POSTFIX);
  397.             SetWTitle(m^^.w, s);
  398.             m^^.whenDone := @partWindow; { XX }
  399.         end;
  400.     end;
  401.  
  402. procedure GetAllWindows (channels, queries, chats: boolean; sepa: char; var s: string);
  403.     var
  404.         p: CPtr;
  405.         s0: str255;
  406.         t: (non, chn, que, dcc);
  407.     begin
  408.         p := CW;
  409.         s := '';
  410.         while p <> nil do begin
  411.             GetWTitle(p^.w^^.w, s0);
  412.             if s0[1] = DCC_CHAT_PREFIX then
  413.                 t := dcc
  414.             else if IsChannel(s0) then
  415.                 t := chn
  416.             else if s0[1] = '(' then
  417.                 t := non
  418.             else
  419.                 t := que;
  420.             if (channels and (t = chn)) or (queries and (t = que)) or (chats and (t = dcc)) then
  421.                 s := concat(s, sepa, s0);
  422.             p := p^.n;
  423.         end;
  424.         if s[1] = sepa then
  425.             delete(s, 1, 1);
  426.     end;
  427.  
  428. end.